package com.joey.cloud.flowable.controller;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.joey.cloud.communal.utils.ResponseUtil;
import com.joey.cloud.flowable.service.FlowProcessService;
import com.joey.cloud.flowable.service.FlowUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.impl.identity.Authentication;
import org.flowable.engine.*;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;

/**
 * 流程控制类
 */
@Api(tags = "flow流程管理")
@Controller
@RequestMapping(value = "flowable/process")
@Slf4j
public class FlowableProcessController {
    @Autowired
    RepositoryService repositoryService;
    @Autowired
    RuntimeService runtimeService;
    @Autowired
    TaskService taskService;
    @Resource
    HistoryService historyService;
    @Resource
    FlowProcessService flowProcessService;
    @Resource
    FlowUserService flowUserService;


    @ApiOperation(value = "启动流程")
    @ApiImplicitParams({
            @ApiImplicitParam(name="userId",value="流程发起人id",required=true,paramType="form"),
            @ApiImplicitParam(name="solKey",value="流程solKey",required=true,paramType="form"),
            @ApiImplicitParam(name="businessKey",value="业务标识",required=true,paramType="form"),
            @ApiImplicitParam(name="paramJson",value="流程参数序列化字符串",required=true,paramType="form")
    })
    @PostMapping(value = "startProcess")
    @ResponseBody
    public ResponseUtil startProcess(String userId,String solKey,String businessKey, String paramJson) {
        if(StrUtil.isEmpty(solKey)){
            return ResponseUtil.error("流程solKey不能为空");
        }
        if(StrUtil.isEmpty(businessKey)){
            return ResponseUtil.error("业务标识businessKey不能为空");
        }
        if(StrUtil.isEmpty(paramJson)){
            return ResponseUtil.error("流程参数paramJson不能为空");
        }
        try {
            //流程发起人
            Authentication.setAuthenticatedUserId(flowUserService.getCurrentUserId());
            HashMap<String, Object> param = JSONObject.parseObject(paramJson, HashMap.class);
            ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(solKey,businessKey,param);
            log.info("流程启动成功，流程id="+processInstance.getId());
            return ResponseUtil.success(processInstance.getId());
        }catch (Exception e){
            log.error("流程启动出错，流程id="+solKey,e);
            return ResponseUtil.error();
        }
    }

    @ApiOperation(value = "终止流程")
    @ApiImplicitParams({
            @ApiImplicitParam(name="processInstanceId",value="流程实例id",required=true,paramType="form"),
            @ApiImplicitParam(name="reason",value="终止原因",required=true,paramType="form")
    })
    @PostMapping(value = "stopProcess")
    @ResponseBody
    public ResponseUtil stopProcess(String processInstanceId,String reason) {
        if(StrUtil.isEmpty(processInstanceId)){
            return ResponseUtil.error("流程实例id不能为空");
        }
        try {
            Authentication.setAuthenticatedUserId(flowUserService.getCurrentUserId());
            runtimeService.deleteProcessInstance(processInstanceId,reason);
            return ResponseUtil.success();
        }catch (Exception e){
            log.error("终止流程出错，流程实例id="+processInstanceId,e);
            return ResponseUtil.error();
        }
    }
    @ApiOperation(value = "挂起流程")
    @ApiImplicitParams({
            @ApiImplicitParam(name="processInstanceId",value="流程实例id",required=true,paramType="form")
    })
    @PostMapping(value = "handUpProcess")
    @ResponseBody
    public ResponseUtil handUpProcess(String processInstanceId) {
        if(StrUtil.isEmpty(processInstanceId)){
            return ResponseUtil.error("流程实例id不能为空");
        }
        try {
            Authentication.setAuthenticatedUserId(flowUserService.getCurrentUserId());
            runtimeService.suspendProcessInstanceById(processInstanceId);
            return ResponseUtil.success();
        }catch (Exception e){
            log.error("挂起流程出错，流程实例id="+processInstanceId,e);
            return ResponseUtil.error();
        }
    }
    @ApiOperation(value = "唤醒流程")
    @ApiImplicitParams({
            @ApiImplicitParam(name="processInstanceId",value="流程实例id",required=true,paramType="form")
    })
    @PostMapping(value = "activateProcess")
    @ResponseBody
    public ResponseUtil activateProcess(String processInstanceId) {
        if(StrUtil.isEmpty(processInstanceId)){
            return ResponseUtil.error("流程实例id不能为空");
        }
        try {
            Authentication.setAuthenticatedUserId(flowUserService.getCurrentUserId());
            runtimeService.activateProcessInstanceById(processInstanceId);
            return ResponseUtil.success();
        }catch (Exception e){
            log.error("唤醒流程出错，流程实例id="+processInstanceId,e);
            return ResponseUtil.error();
        }
    }


    @ApiOperation(value = "获取流程变量")
    @ApiImplicitParams({
            @ApiImplicitParam(name="processInstanceId",value="流程id",required=true,paramType="query")
    })
    @GetMapping(value = "getVariable")
    @ResponseBody
    public ResponseUtil getVariable(String processInstanceId){
        try {
            if(StrUtil.isEmpty(processInstanceId)){
                return ResponseUtil.error("流程processInstanceId不能为空");
            }
            Map<String, Object> variables = runtimeService.getVariables(processInstanceId);
            return ResponseUtil.success(variables);
        }catch (Exception e){
            log.error("获取流程变量出错，流程processInstanceId="+processInstanceId,e);
            return ResponseUtil.error();
        }
    }

    @ApiOperation(value = "设置流程变量")
    @ApiImplicitParams({
            @ApiImplicitParam(name="processInstanceId",value="流程id",required=true,paramType="form"),
            @ApiImplicitParam(name="paramJson",value="流程变量参数序列化字符串",required=true,paramType="form")
    })
    @PutMapping(value = "setVariable")
    @ResponseBody
    public ResponseUtil setVariable(String processInstanceId,String paramJson){
        try {
            if(StrUtil.isEmpty(processInstanceId)){
                return ResponseUtil.error("流程processInstanceId不能为空");
            }
            if(StrUtil.isEmpty(paramJson)){
                return ResponseUtil.error("流程变量参数paramJson不能为空");
            }
            HashMap<String, Object> param = JSONObject.parseObject(paramJson, HashMap.class);
            runtimeService.setVariables(processInstanceId,param);
            return ResponseUtil.success();
        }catch (Exception e){
            log.error("设置流程变量出错，流程processInstanceId="+processInstanceId,e);
            return ResponseUtil.error();
        }
    }

    @ApiOperation(value = "获取流程实例流程图")
    @ApiImplicitParams({
            @ApiImplicitParam(name="processInstanceId",value="流程实例id",required=true,paramType="form")
    })
    @GetMapping(value = "processDiagram")
    public void genProcessDiagram(HttpServletResponse httpServletResponse, String processInstanceId) throws Exception {
        OutputStream out = null;
        InputStream in = null;
        try {
            in = flowProcessService.getDiagramByProcessId(processInstanceId);
            byte[] buf = new byte[1024];
            int legth = 0;
            out = httpServletResponse.getOutputStream();
            while ((legth = in.read(buf)) != -1) {
                out.write(buf, 0, legth);
            }
        }catch (Exception e){
            log.error("获取流程图出错",e);
        }finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
    }
    @ApiOperation(value = "获取流程定义流程图")
    @ApiImplicitParams({
            @ApiImplicitParam(name="processDefinitionId",value="流程定义id",required=true,paramType="form")
    })
    @GetMapping(value = "definitionDiagram")
    public void genDefinitionDiagram(HttpServletResponse httpServletResponse, String processDefinitionId) throws Exception {
        OutputStream out = null;
        InputStream in = null;
        try {
            in = flowProcessService.getDiagramByDefinitionId(processDefinitionId);
            byte[] buf = new byte[1024];
            int legth = 0;
            out = httpServletResponse.getOutputStream();
            while ((legth = in.read(buf)) != -1) {
                out.write(buf, 0, legth);
            }
        }catch (Exception e){
            log.error("获取流程图出错",e);
        }finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
    }

}
